﻿//
// Created by D on 2022/11/8.
//
#include "graphicsview.h"
#include <cmath>
#include <QAction>
#include <QKeyEvent>
#include <QMenu>
#include <QOpenGLWidget>

const auto DEFAULT_WIDTH  = 320;
const auto DEFAULT_HEIGHT = 240;

GraphicsView::GraphicsView(QGraphicsScene* scene, QWidget* parent, bool useOpenGL)
    : QGraphicsView(scene, parent)
{
    // 经过实测，不适用OpenGL反而响应更快
    if (useOpenGL) {
        // QOpenGLWidget 有bug，Qt5最好使用QGLWidget
        setViewport(new QOpenGLWidget(this));
    }
    setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    createActions();
    createConnections();
    createMenu();
}

void GraphicsView::createActions()
{
    m_viewZoomInAction = new QAction(QIcon(":/zoom-in.png"), tr("Zoom In"), this);
    m_viewZoomInAction->setShortcut(QKeySequence::ZoomIn);
    m_viewZoomOutAction = new QAction(QIcon(":/zoom-out.png"), tr("Zoom Out"), this);
    m_viewZoomOutAction->setShortcut(QKeySequence::ZoomOut);
    m_viewZoomFitAction = new QAction(QIcon(":/zoom-fit.png"), tr("Zoom Fit"), this);
    m_viewZoomFitAction->setShortcut(tr("Ctrl+*"));
    m_viewZoomOriginalAction = new QAction(QIcon(":/zoom-original.png"), tr("Zoom Original"), this);
    m_viewZoomOriginalAction->setShortcut(tr("Ctrl+0"));
}

void GraphicsView::createConnections()
{
    connect(m_viewZoomInAction, SIGNAL(triggered()), this, SLOT(zoomIn()));
    connect(m_viewZoomOutAction, SIGNAL(triggered()), this, SLOT(zoomOut()));
    connect(m_viewZoomFitAction, SIGNAL(triggered()), this, SLOT(zoomFitView()));
    connect(m_viewZoomOriginalAction, SIGNAL(triggered()), this, SLOT(zoomOriginal()));
}

void GraphicsView::createMenu()
{
    setContextMenuPolicy(Qt::ActionsContextMenu);
    addAction(m_viewZoomInAction);
    addAction(m_viewZoomOutAction);
    addAction(m_viewZoomFitAction);
    addAction(m_viewZoomOriginalAction);
}

void GraphicsView::scaleBy(double factor)
{
    scale(factor, factor);
}

void GraphicsView::wheelEvent(QWheelEvent* event)
{
    const auto delta = event->angleDelta().y();
    scaleBy(std::pow(4.0 / 3.0, (delta / 240.0)));
}

void GraphicsView::zoomIn()
{
    scaleBy(1.1);
}

void GraphicsView::zoomOut()
{
    scaleBy(1.0 / 1.1);
}

void GraphicsView::zoomFitView()
{
    const auto rect = sceneRect();
    fitInView(rect, Qt::KeepAspectRatio);
}

void GraphicsView::zoomOriginal()
{
    setTransform({});
}

QSize GraphicsView::minimumSizeHint() const
{
    // QAbstractScrollArea::minimumSizeHint();
    return { DEFAULT_WIDTH, DEFAULT_HEIGHT };
}
